﻿using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace sinetd.Services
{
    public class ConnectionPoll : ServerController
    {
        public ConnectionPoll()
        {
            UserConnections = new Dictionary<IConnectionIO, object>();
            ConnectionThreads = new Dictionary<IConnectionIO, Thread>();
        }

        public Dictionary<IConnectionIO, object> UserConnections;

        public Dictionary<IConnectionIO, Thread> ConnectionThreads;

        public List<IConnectionIO> Connections
        {
            get { return UserConnections.Keys.ToList(); }
        }

        public IConnectionIO GetUserConnection(object user)
        {
            IEnumerable<KeyValuePair<IConnectionIO, object>> list = UserConnections.Where(x => x.Value != null && x.Value.Equals(user));
            return list.Count() > 0 ? list.First().Key : null;
        }

        protected override void Begin()
        {
        }

        protected override void Run()
        {
            IConnectionIO[] connections = new IConnectionIO[Connections.Count];
            Connections.CopyTo(connections);
            foreach (IConnectionIO conn in connections)
            {
                if (ConnectionThreads.ContainsKey(conn))
                {
                    if (!ConnectionThreads[conn].IsAlive)
                    {
                        ConnectionThreads[conn] = new Thread(() =>
                        {
                            OnHandle(conn, UserConnections[conn]);
                        });
                        ConnectionThreads[conn].Start();
                    }
                }
            }
        }

        protected override void End()
        {
            foreach (KeyValuePair<IConnectionIO, Thread> kvp in ConnectionThreads)
            {
                //((Protocols.IProtocol)kvp.Key).Close();//use this
                if (kvp.Value.IsAlive)
                {
                    kvp.Value.Join(10);
                    kvp.Value.Abort(); // or this -> to think about this
                }
            }
        }

        public delegate void HandleHandler(IConnectionIO iConnectionIO, object p);

        private void OnHandle(IConnectionIO iConnectionIO, object p)
        {
            if (Handle != null) Handle(iConnectionIO, p);
        }

        public event HandleHandler Handle;

        public void NewConnection(IConnectionIO conn)
        {
            UserConnections.Add(conn, null);
            ConnectionThreads.Add(conn, new Thread(() => { }));
        }

        public void RemoveConnection(object login)
        {
            IConnectionIO conn = GetUserConnection(login);
            if (conn != null)
                RemoveConnection(conn);
        }

        public void RemoveConnection(IConnectionIO conn)
        {
            UserConnections.Remove(conn);
            ConnectionThreads.Remove(conn);
        }
    }
}
